package cn.wolfcode.service.impl;

import cn.wolfcode.common.exception.BusinessException;
import cn.wolfcode.common.web.Result;
import cn.wolfcode.domain.*;
import cn.wolfcode.mapper.OrderInfoMapper;
import cn.wolfcode.mapper.PayLogMapper;
import cn.wolfcode.mapper.RefundLogMapper;
import cn.wolfcode.mq.OrderMQResult;
import cn.wolfcode.redis.SeckillRedisKey;
import cn.wolfcode.service.IOrderInfoService;
import cn.wolfcode.service.ISeckillProductService;
import cn.wolfcode.util.IdGenerateUtil;
import cn.wolfcode.web.feign.IntergralFeginApi;
import cn.wolfcode.web.feign.PayFeginApi;
import cn.wolfcode.web.msg.SeckillCodeMsg;
import io.seata.spring.annotation.GlobalTransactional;
import org.checkerframework.checker.index.qual.GTENegativeOne;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.sound.midi.MidiDevice;
import java.util.Date;

/**
 * Created by wolfcode-lanxw
 */
@Service
public class OrderInfoSeviceImpl implements IOrderInfoService {
    @Autowired
    private ISeckillProductService seckillProductService;
    @Autowired
    private OrderInfoMapper orderInfoMapper;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private PayLogMapper payLogMapper;
    @Autowired
    private RefundLogMapper refundLogMapper;
    @Autowired
    private IntergralFeginApi intergralFeginApi;

    @Override
    public OrderInfo getOrderByAndSeckillId(String phone, Long seckillId) {
        return orderInfoMapper.getOrderByAndSeckillId(phone,seckillId);
    }

    @Override
    public String doSeckill(SeckillProductVo seckillProductVo, String phone) {
        //扣除数据库的库存
        int count = seckillProductService.derStock(seckillProductVo.getId());
        if (count == 0){
            throw new BusinessException(SeckillCodeMsg.SECKILL_STOCK_OVER);
        }
        //创建秒杀订单
        String order = creareOrderInfo(seckillProductVo,phone);
        return order;
    }

    //创建秒杀订单
    private String creareOrderInfo(SeckillProductVo seckillProductVo, String phone) {
        OrderInfo orderInfo = new OrderInfo();
        BeanUtils.copyProperties(seckillProductVo,orderInfo);
        orderInfo.setUserId(Long.parseLong(phone));//设置用户id
        orderInfo.setCreateDate(new Date());//订单创建时间
        orderInfo.setSeckillDate(seckillProductVo.getStartDate());//秒杀的时间（年月日）
        orderInfo.setSeckillId(seckillProductVo.getId());//秒杀id
        orderInfo.setSeckillTime(seckillProductVo.getTime());//秒杀场次
        orderInfo.setOrderNo(String.valueOf(IdGenerateUtil.get().nextId())); //订单编号
        orderInfoMapper.insert(orderInfo);
        //往Redis 中存储Set集合，存储的内容  seckillId:手机号码
        String realKey = SeckillRedisKey.SECKILL_ORDER_SET.getRealKey(String.valueOf(seckillProductVo.getId()));
        redisTemplate.opsForSet().add(realKey,phone);
        return orderInfo.getOrderNo();
    }

    @Override
    public OrderInfo find(String orderNo) {
        return orderInfoMapper.find(orderNo);
    }

    @Override
    public void cancelOrder(OrderMQResult orderMQResult) {
        //通过订单编号获取到这个订单信息
        OrderInfo orderInfo = find(orderMQResult.getOrderNo());
        if (OrderInfo.STATUS_ARREARAGE.equals(orderInfo.getStatus())) {
            //订单15分钟没有支付
            //1.取消订单，订单状态改为超时取消
            int count = orderInfoMapper.updateCancelStatus(orderMQResult.getOrderNo(), OrderInfo.STATUS_TIMEOUT);
            if (count == 0){
                //说明在更新之前，已经有其他线程对订单状态进行修改了
                return;
            }
            //2订单超时，商品没有卖出，给库存执行加一操作
            seckillProductService.incrStockCount(orderMQResult.getSeckillId());
            //3同步数据库缓存到Redis与预缓存中
            seckillProductService.syncStorckCountToRedis(orderMQResult.getTime(),orderMQResult.getSeckillId());
        }
    }

    @Value("${pay.returnUrl}")
    private String returnUrl;
    @Value("${pay.notifyUrl}")
    private String notifyUrl;
    @Autowired
    private PayFeginApi payFeginApi;

    @Override
    public String payOnLine(String orderNo) {
        //获取到当前的订单对象
        OrderInfo orderInfo = find(orderNo);
        PayVo vo = new PayVo();
        vo.setTotalAmount(String.valueOf(orderInfo.getSeckillPrice()));
        vo.setOutTradeNo(orderInfo.getOrderNo());
        vo.setSubject(orderInfo.getProductName());
        vo.setBody(orderInfo.getProductName());
        vo.setNotifyUrl(notifyUrl);
        vo.setReturnUrl(returnUrl);
        //发送远程服务到支付服务
        Result<String> result = payFeginApi.pay(vo);
        if (result == null ||result.hasError()){
            throw new BusinessException(SeckillCodeMsg.PAY_SERVER_ERROR);
        }
        return result.getData();
    }


    @Override
    public void paySuccess(String orderNo) {
        //第一个参数：订单编号，第二个参数：订单状态，第三个参数：支付类型
        int count = orderInfoMapper.changePayStatus(orderNo, OrderInfo.STATUS_ACCOUNT_PAID, OrderInfo.PAYTYPE_ONLINE);
        if (count == 0){
            //在支付回调之前，刚好有其他逻辑修改了订单，状态发生了修改
            //往MQ中发送信息，走退款逻辑
        }
    }

    @Override
    @GlobalTransactional
    public void refund(String orderNo) {
        OrderInfo orderInfo = find(orderNo);
        if (OrderInfo.PAYTYPE_ONLINE.equals(orderInfo.getPayType())){
            //在线支付（退款）,调用支付宝退款接口
            refundOnline(orderInfo);
        }else {
            //积分支付（退款）
            refundIntergral(orderInfo);
        }
    }

    //积分退款逻辑
    public void refundIntergral(OrderInfo orderInfo) {
        OperateIntergralVo vo = new OperateIntergralVo();
        vo.setUserId(orderInfo.getUserId());
        vo.setValue(orderInfo.getIntergral());
        //远程调用积分用户，给退款积分用户加积分
        Result result = intergralFeginApi.incrIntergral(vo);
        if (result==null ||result.hasError()){
            throw new BusinessException(SeckillCodeMsg.INTERGRAL_SERVER_ERROR);
        }
        //修改订单状态
        orderInfoMapper.changeRefundStatus(orderInfo.getOrderNo(),OrderInfo.STATUS_REFUND);
        int i = 1/0;
    }

    //支付宝退款方法
    private void refundOnline(OrderInfo orderInfo) {
        RefundVo refundVo = new RefundVo();
        refundVo.setOutTradeNo(orderInfo.getOrderNo());
        refundVo.setRefundAmount(String.valueOf(orderInfo.getSeckillPrice()));
        refundVo.setRefundReason("用户申请退款");
        Result<Boolean> refund = payFeginApi.refund(refundVo);
        if (refund==null||refund.hasError()||!refund.getData()){
            throw new BusinessException(SeckillCodeMsg.PAY_SERVER_ERROR);
        }
        //修改订单状态，状态变成已退款
        orderInfoMapper.changeRefundStatus(orderInfo.getOrderNo(),OrderInfo.STATUS_REFUND);
    }

    @Override
    @GlobalTransactional
    public void payIntergral(String orderNo) {
        OrderInfo orderInfo = find(orderNo);
        OperateIntergralVo vo = new OperateIntergralVo();
        vo.setUserId(orderInfo.getUserId());
        vo.setValue(orderInfo.getIntergral());
        //发送远程调用到积分服务中进行积分的扣除
        Result result = intergralFeginApi.decrIntergral(vo);
        if (result==null || result.hasError()){
            throw new BusinessException(SeckillCodeMsg.INTERGRAL_SERVER_ERROR);
        }
        //修改订单状态，修改成已付款 + 积分支付
        orderInfoMapper.changePayStatus(orderNo,OrderInfo.STATUS_ACCOUNT_PAID,OrderInfo.PAYTYPE_INTERGRAL);
//        int i = 1/0;
    }
}